Skip to content

feat: Support cross-database evaluation with SQLite ground truth#465

Open
arieljassan wants to merge 4 commits into
GoogleCloudPlatform:mainfrom
arieljassan:feat/bird-xa-benchmark
Open

feat: Support cross-database evaluation with SQLite ground truth#465
arieljassan wants to merge 4 commits into
GoogleCloudPlatform:mainfrom
arieljassan:feat/bird-xa-benchmark

Conversation

@arieljassan

Copy link
Copy Markdown
Member

Overview

This PR adds support for running the BIRD benchmark (and similar cross-database SQL evaluations) on BigQuery while using local SQLite databases for ground truth reference execution.
When evaluating AI-generated queries on BigQuery against reference queries written in SQLite syntax (e.g., using STRFTIME or SQLite math functions), BigQuery cannot execute the reference queries directly. This update introduces a hybrid bridging mechanism that dynamically resolves reference answers from local SQLite files while evaluating generated queries on BigQuery.

Key Changes

  • evalbench/databases/bigquery.py: Implements the required ensure_database_exists abstract method on BQDB to fulfill the base DB class contract.
  • evalbench/scorers/sqlite_bridge.py & llmrater.py: Adds conditional ground truth resolution. When golden_error occurs and a hybrid judge is configured, LLMRater automatically fetches the true reference execution rows from the local SQLite database.
  • hybrid_xa_judge.py: Adds a self-contained Execution Accuracy (XA) evaluator script for PythonScorer. It normalizes across engine data types (Decimal/Int64 vs float), ignores column header differences, and compares rows order-independently.

Verification

  • Performed functional end-to-end benchmark tests across dual BIRD evaluation datasets (california_schools and card_games).
  • Confirmed functional ground truth resolution from local SQLite reference tables during live BigQuery evaluation runs.
  • Verified clean telemetry data warehousing into BigQuery (FLOAT64 score compatibility).

@arieljassan arieljassan requested a review from IsmailMehdi as a code owner June 28, 2026 17:26
@arieljassan

Copy link
Copy Markdown
Member Author

/gcbrun

@IsmailMehdi IsmailMehdi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solves a real problem (cross-engine BIRD eval on BQ), but a few correctness issues to address. Inline comments cover the file-specific items. Three cross-cutting points that don't fit a specific line:

No tests for any of the new code. Both sqlite_bridge.py and hybrid_xa_judge.py are trivially unit-testable (in-memory SQLite via sqlite3.connect(":memory:"), mock sys.argv). Without tests the fragile bits flagged inline will silently rot. Minimum I'd want to see: test_get_sqlite_ground_truth_uses_named_db (after the #2 fix), test_compare_result_sets_handles_decimal_vs_float, test_compare_result_sets_ignores_column_names_and_row_order, test_hybrid_xa_judge_main_with_matching_results.

No documentation in docs/configs/run-config.md or dataset-config docs for this new mode. PRs #453 and #459 got the same note — easier to add docs at PR time than to remember later.

PR description "Verification" is functional/manual only — no automated test references. Worth at least pointing to a scenario YAML that exercises the hybrid path so others can repro the test. Also: if you confirm the uv run --isolated import issue (inline comment on hybrid_xa_judge.py:10), worth describing in the PR how the manual verification got past that — I may be misreading the invocation.

Comment thread evalbench/databases/bigquery.py Outdated
Comment thread evalbench/scorers/sqlite_bridge.py Outdated
Comment thread evalbench/scorers/sqlite_bridge.py Outdated
Comment thread evalbench/scorers/sqlite_bridge.py Outdated
Comment thread evalbench/scorers/llmrater.py Outdated
Comment thread hybrid_xa_judge.py Outdated
Comment thread evalbench/scorers/judges/hybrid_xa_judge.py
Comment thread evalbench/scorers/judges/hybrid_xa_judge.py
@IsmailMehdi

Copy link
Copy Markdown
Collaborator

Maybe this should be built as a tool instead of inline with evals. wdyt ?

@arieljassan arieljassan force-pushed the feat/bird-xa-benchmark branch from bb25c95 to 1c07b41 Compare June 30, 2026 10:28
@arieljassan

Copy link
Copy Markdown
Member Author

Thank you for the review! addressing your general comments:

No tests for any of the new code.

Added 7 unit tests covering both components under evalbench/test/:

  • sqlite_bridge_test.py: Verifies dynamic SQLite path loading and fallback error resilience when a database file is missing.
  • hybrid_xa_judge_test.py: Verifies all result set cell normalization rules (float rounding to 4 decimal places, string .0 suffix stripping, lexicographical sorting, ignoring column names, matching float vs Decimal types) and tests stdin/stdout payload JSON parsing under the sandbox execution.

No documentation in docs/configs/run-config.md or dataset-config docs for this new mode.

Added documentation detailing the new configurations:

  • run-config.md: Documented hybrid_ground_truth under llmrater, added details for configuring the generic python_scorer, and documented the cell normalization rules of the included hybrid_xa_judge.py script.
  • dataset-config.md: Added a note explaining how the golden_sql dialect should map to the execution engine dialect (e.g. "bigquery") even if the reference query is written in SQLite syntax.
  • Example YAML: Added datasets/bird/example_hybrid_run_config.yaml to provide a clear reference on how to construct a hybrid evaluation configuration.

PR description "Verification" is functional/manual only — no automated test references.

Added unit tests and a functional test:

.venv_eb/bin/python3 -m unittest evalbench/test/sqlite_bridge_test.py evalbench/test/hybrid_xa_judge_test.py

And added a note explaining how the sandbox execution (uv run --isolated) is handled via duplicating get_sqlite_ground_truth directly inside hybrid_xa_judge.py to prevent import issues in isolated environments.

@IsmailMehdi

Copy link
Copy Markdown
Collaborator

/gcbrun

self.client = bigquery.Client(project=self.project_id)
self.tmp_users = []

def ensure_database_exists(self, database_name: str) -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dead code, see line 183.

@IsmailMehdi IsmailMehdi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once minor dupe method removed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants